package com.line.config.datasource;

import java.util.Map;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * 主数据库Srping data jpa数据源的配置
 *
 * @author JustinYang
 * @version 1.0
 * @since 2016-06-16
 *
 */
// 等价 与XML中配置beans；用@Bean标注方法等价于XML中配置bean
@Configuration
// 开启注解式事物的支持
@EnableTransactionManagement
// 配置JPA repository支持
// entityManagerFactoryRef：实体管理工厂引用名称，对应到@Bean注解对应的方法
// transactionManagerRef:事务管理工厂引用名称，对应到@Bean注解对应的方法
// basePackages:扫描指定目录下的repository，可指定多个
@EnableJpaRepositories(entityManagerFactoryRef = "mysqlEntityManagerFactory"// 指定实体管理工厂
		, transactionManagerRef = "mysqlTransactionManager", // 指定事务支持对象
		basePackages = { "com.line.dao" }) // 指定扫描的路径
public class MysqlRepositoryConfig {

	@Autowired
	private JpaProperties jpaProperties; // JPA配置加载

	@Autowired
	@Qualifier("mysqlDs") // 通过byName方式注入bean，并且可以存在多个相同的bean
	private DataSource mysqlDs;// 设置主库数据源

	/**
	 * 创建实体管理对象
	 *
	 * @param builder
	 *            实体管理工厂构建器
	 * @return 实体管理对象
	 */
	@Primary // 优先级
	@Bean(name = "mysqlEntityManager") // 设置实体管理对象Bean名称
	public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
		return entityManagerFactoryPrimary(builder).getObject().createEntityManager(); // 通过实体管理工厂创建实体管理对象
	}

	/**
	 * 创建实体管理工厂
	 *
	 * @param builder
	 *            实体管理工厂构建器
	 * @return 工厂对象
	 */
	@Primary // 优先级
	@Bean(name = "mysqlEntityManagerFactory") // 设置实体管理工厂bean名称
	public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
		return builder.dataSource(mysqlDs)// 将数据源添加至实体管理工厂
				.properties(getVendorProperties(mysqlDs)) // 加载数据源配置
				.packages("com.line.model.entity") // 设置实体类所在位置
				.persistenceUnit("mysqlPersistenceUnit").build(); // 构建工厂对象
	}

	/**
	 * 将实体管理对象添加事务支持
	 *
	 * @param builder
	 *            实体管理工厂构建器
	 * @return
	 */
	@Primary // 优先级
	@Bean(name = "mysqlTransactionManager") // 设置事务bean名称
	public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
		return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
	}

	/**
	 * 加载配置信息
	 *
	 * @param dataSource
	 *            数据源
	 * @return 配置缓存
	 */
	private Map<String, String> getVendorProperties(DataSource dataSource) {
		return jpaProperties.getProperties();
	}
}
